#ifndef __M_CONSUMER_H__
#define __M_CONSUMER_H__
#include"../mqcommon/mq_helper.hpp"
#include"../mqcommon/mq_msg.pb.h"
#include<iostream>
#include<unordered_map>
#include<mutex>
#include<memory>
#include<vector>
#include<functional>

namespace xiang11mq
{

//消费者标识 消息的属性 消息的主体
using ConsumerCallback = std::function<void(const std::string tag, BasicProperties *bp, const std::string body)>;
//消费者对象结构
struct Consumer
{
    using ptr = std::shared_ptr<Consumer>;

    std::string tag;                    //消费者标识
    std::string subscribe_queue;        //消费者订阅的队列名称
    bool auto_ack;                      //自动确认标志
    ConsumerCallback callback;

    Consumer(){
        DLOG("new Channel by default: %p", this);
    }
    Consumer(const std::string &ctag, const std::string &csubscribe_queue, bool ack, const ConsumerCallback &cb)
        :tag(ctag)
        ,subscribe_queue(csubscribe_queue)
        ,auto_ack(ack)
        ,callback(cb)
    {
        DLOG("new consumer: %p", this);
    }
    ~Consumer()
    {
        DLOG("del consumer: %p", this);
    }
};

//以队列为单元的消费者管理结构
class QueueConsumer
{
public:
    using ptr = std::shared_ptr<QueueConsumer>;
    QueueConsumer(const std::string &qname)
        :_qname(qname)
        ,_rr_seq(0)
    {}
    //新增一个消费者
    Consumer::ptr create(const std::string &ctag, const std::string &subscribe_queue, bool ack_flag, const ConsumerCallback &cb)
    {
        //1.加锁
        std::unique_lock<std::mutex> lock(_mutex);
        //2.判断消费者是否重复
        for(const auto& consumer : _consumers)
        {
            if(consumer->tag == ctag)
            {
                DLOG("消费者重复%s", ctag.c_str());
                return Consumer::ptr();
            }
        }
        //3.没有重复则新增--构造对象
        auto consumer = std::make_shared<Consumer>(ctag, subscribe_queue, ack_flag, cb);
        //4.添加管理后返回对象
        _consumers.push_back(consumer);

        return consumer;
    }
    //删除一个消费者
    void remove(const std::string &ctag)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        for(auto it = _consumers.begin(); it != _consumers.end(); it ++)
        {
            if((*it)->tag == ctag)
            {
                _consumers.erase(it);
                return;
            }
        }
        DLOG("要删除的消费者不存在 %s", ctag.c_str());
        return;
    }
    //获取一个消费者消费:: RR轮转获取
    Consumer::ptr choose()
    {
        //1.加锁
        std::unique_lock<std::mutex> lock(_mutex);
        if(_consumers.size() == 0)
            return Consumer::ptr();
        //2.获取当前轮转下标
        int idx = _rr_seq % _consumers.size();
        _rr_seq++;
        //3.获取对象 返回
        return _consumers[idx];
    }
    //是否有消费者
    bool empty()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        return _consumers.empty();
    }
    //消费者是否存在
    bool exists(const std::string &ctag)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        for (auto it = _consumers.begin(); it != _consumers.end(); it++)
        {
            if ((*it)->tag == ctag)
            {
                return true;
            }
        }

        DLOG("消费者不存在 %s", ctag.c_str());
        return false;
    }
    //清理
    void clear()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _consumers.clear();
        _rr_seq = 0;
    }
private:
    std::string _qname;                     //订阅的消息队列号
    std::mutex _mutex;
    uint64_t _rr_seq;                       //轮转序号
    std::vector<Consumer::ptr> _consumers;
};

//消费者队列管理结构
class ConsumerManager
{
public:
    using ptr = std::shared_ptr<ConsumerManager>;
    ConsumerManager(){}
    //初始化消费者队列
    void initQueueConsumer(const std::string &qname)
    {
        //1.加锁
        std::unique_lock<std::mutex> lock(_mutex);
        //2.重复判断
        auto it = _qconsumers.find(qname);
        if(it != _qconsumers.end())
        {
            DLOG("要初始化的消费者队列已经存在 %s", qname.c_str());
            return;
        }
        //3.新增
        auto consumers = std::make_shared<QueueConsumer>(qname);
        _qconsumers.insert(std::make_pair(qname, consumers));
    }
    //销毁消费者队列
    void destroyQueueConsumer(const std::string &qname)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _qconsumers.erase(qname);
    }
    //向指定队列创建消费者
    Consumer::ptr create(const std::string &qname, const std::string &ctag, bool ack_flag, const ConsumerCallback &cb)
    {
        QueueConsumer::ptr qcp;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _qconsumers.find(qname);
            if (it == _qconsumers.end())
            {
                DLOG("要新增消费者的消费者队列不存在 %s", qname.c_str());
                return Consumer::ptr();
            }
            qcp = it->second;
        }
        return qcp->create(ctag, qname, ack_flag, cb);
    }
    //向指定队列删除消费者
    void remove(const std::string &qname, const std::string &ctag)
    {
        QueueConsumer::ptr qcp;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _qconsumers.find(qname);
            if (it == _qconsumers.end())
            {
                DLOG("要删除消费者的消费者队列不存在 %s", qname.c_str());
                return;
            }
            qcp = it->second;
        }
        qcp->remove(ctag);

    }
    //从指定队列获取消费者
    Consumer::ptr choose(const std::string &qname)
    {
        QueueConsumer::ptr qcp;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _qconsumers.find(qname);
            if (it == _qconsumers.end())
            {
                DLOG("要获取消费者的消费者队列不存在 %s", qname.c_str());
                return Consumer::ptr();
            }
            qcp = it->second;
        }
        return qcp->choose();

    }
    //判断指定队列是否为空
    bool empty(const std::string &qname)
    {
        QueueConsumer::ptr qcp;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _qconsumers.find(qname);
            if (it == _qconsumers.end())
            {
                DLOG("要判判断指定队列是否为空的消费者队列不存在 %s", qname.c_str());
                return false;
            }
            qcp = it->second;
        }
        return qcp->empty();
    }
    //判断指定队列是否存在
    bool exists(const std::string &qname, const std::string &ctag)
    {
        QueueConsumer::ptr qcp;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _qconsumers.find(qname);
            if (it == _qconsumers.end())
            {
                DLOG("要判断指定队列是否存在的消费者队列不存在 %s", qname.c_str());
                return false;
            }
            qcp = it->second;
        }
        return qcp->exists(ctag);

    }
    //清理
    void clear()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _qconsumers.clear();
    }

private:
    std::mutex _mutex;
    std::unordered_map<std::string, QueueConsumer::ptr> _qconsumers;
};


}


#endif